bitkeeper revision 1.1585 (42988c63d2BDHoRycJzKDjIR50X5Sw)
authorleendert@watson.ibm.com[kaf24] <leendert@watson.ibm.com[kaf24]>
Sat, 28 May 2005 15:21:07 +0000 (15:21 +0000)
committerleendert@watson.ibm.com[kaf24] <leendert@watson.ibm.com[kaf24]>
Sat, 28 May 2005 15:21:07 +0000 (15:21 +0000)
[PATCH] [PATCH] VMX world switch does not handle all cases

The latest world switch modification does not handle all cases. Specifically,
when a partition enables CR0.PG|CR0.PE and performs a world switch at the
the same time. The patch below handles this case.

Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
xen/arch/x86/vmx.c

index eaa73de5a40b73b148e0b6021570f199b4696c15..895c8c11cee1a64cec7401173c8f5fae44461b92 100644 (file)
@@ -744,8 +744,8 @@ static int vmx_set_cr0(unsigned long value)
     __vmwrite(CR0_READ_SHADOW, value);
 
     VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
-    if ((value & X86_CR0_PE) && (value & X86_CR0_PG) 
-        && !paging_enabled) {
+
+    if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled) {
         /*
          * The guest CR3 must be pointing to the guest physical.
          */
@@ -775,33 +775,39 @@ static int vmx_set_cr0(unsigned long value)
          */
         VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", 
                 d->arch.arch_vmx.cpu_cr3, mfn);
-    } else {
-        if ((value & X86_CR0_PE) == 0) {
-            __vmread(GUEST_EIP, &eip);
-            VMX_DBG_LOG(DBG_LEVEL_1, "Disabling CR0.PE at %%eip 0x%lx\n", eip);
-           if (vmx_assist(d, VMX_ASSIST_INVOKE)) {
-               set_bit(VMX_CPU_STATE_ASSIST_ENABLED,
-                                       &d->arch.arch_vmx.cpu_state);
-               __vmread(GUEST_EIP, &eip);
-               VMX_DBG_LOG(DBG_LEVEL_1,
-                   "Transfering control to vmxassist %%eip 0x%lx", eip);
-               return 0; /* do not update eip! */
-           }
-       } else if (test_bit(VMX_CPU_STATE_ASSIST_ENABLED,
-                                       &d->arch.arch_vmx.cpu_state)) {
+    }
+
+    /*
+     * VMX does not implement real-mode virtualization. We emulate
+     * real-mode by performing a world switch to VMXAssist whenever
+     * a partition disables the CR0.PE bit.
+     */
+    if ((value & X86_CR0_PE) == 0) {
+       __vmread(GUEST_EIP, &eip);
+       VMX_DBG_LOG(DBG_LEVEL_1,
+           "Disabling CR0.PE at %%eip 0x%lx\n", eip);
+       if (vmx_assist(d, VMX_ASSIST_INVOKE)) {
+           set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &d->arch.arch_vmx.cpu_state);
            __vmread(GUEST_EIP, &eip);
            VMX_DBG_LOG(DBG_LEVEL_1,
-               "Enabling CR0.PE at %%eip 0x%lx", eip);
-           if (vmx_assist(d, VMX_ASSIST_RESTORE)) {
-               clear_bit(VMX_CPU_STATE_ASSIST_ENABLED,
+               "Transfering control to vmxassist %%eip 0x%lx\n", eip);
+           return 0; /* do not update eip! */
+       }
+    } else if (test_bit(VMX_CPU_STATE_ASSIST_ENABLED,
+                                       &d->arch.arch_vmx.cpu_state)) {
+       __vmread(GUEST_EIP, &eip);
+       VMX_DBG_LOG(DBG_LEVEL_1,
+           "Enabling CR0.PE at %%eip 0x%lx\n", eip);
+       if (vmx_assist(d, VMX_ASSIST_RESTORE)) {
+           clear_bit(VMX_CPU_STATE_ASSIST_ENABLED,
                                        &d->arch.arch_vmx.cpu_state);
-               __vmread(GUEST_EIP, &eip);
-               VMX_DBG_LOG(DBG_LEVEL_1,
-                   "Restoring to %%eip 0x%lx", eip);
-               return 0; /* do not update eip! */
-           }
+           __vmread(GUEST_EIP, &eip);
+           VMX_DBG_LOG(DBG_LEVEL_1,
+               "Restoring to %%eip 0x%lx\n", eip);
+           return 0; /* do not update eip! */
        }
     }
+
     return 1;
 }